/*
 * Copyright 2007 - 2025 Ralf Wisser.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package net.sf.jailer.ui;

import java.awt.Font;
import java.awt.GridBagConstraints;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import net.sf.jailer.datamodel.Association;
import net.sf.jailer.datamodel.DataModel;
import net.sf.jailer.datamodel.Table;
import net.sf.jailer.ui.AssociationListUI.AssociationModel;
import net.sf.jailer.ui.AssociationListUI.DefaultAssociationModel;

/**
 * Closure Border Dialog.
 * 
 * @author Ralf Wisser
 */
public abstract class ClosureBorderDialog extends javax.swing.JDialog {

	private static final long serialVersionUID = -7151994890007647782L;
	
	protected AssociationListUI associationListUI;
	
	/** Creates new form ClosureBorderDialog */
	public ClosureBorderDialog(java.awt.Frame parent, boolean withInfoLine) {
		super(parent, false);
		initComponents(); UIUtil.initComponents(this);
		if (!withInfoLine) {
			rootNameLabel.setVisible(false);
			jLabel1.setVisible(false);
		}
		
		associationListUI = new AssociationListUI("Remove Restrictions", "Remove Restrictions from selected Associations", false) {
			private static final long serialVersionUID = 1129925600909956307L;
			@Override
			protected void applyAction(Collection<AssociationModel> selection) {
				Collection<Association> associations = new ArrayList<Association>();
				for (AssociationModel associationModel: selection) {
					associations.add(((DefaultAssociationModel) associationModel).association);
				}
				removeRestrictions(associations);
			}
			@Override
			protected void onSelect(AssociationModel association) {
				ClosureBorderDialog.this.onSelect(((DefaultAssociationModel) association).association);
			}
		};
		
		rootNameLabel.setFont(
				rootNameLabel.getFont().deriveFont(
						rootNameLabel.getFont().getStyle() | Font.BOLD,
						rootNameLabel.getFont().getSize()));
		GridBagConstraints gridBagConstraints = new java.awt.GridBagConstraints();
		gridBagConstraints.gridx = 1;
		gridBagConstraints.gridy = 2;
		gridBagConstraints.gridwidth = 2;
		gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
		gridBagConstraints.weightx = 1.0;
		gridBagConstraints.weighty = 1.0;
		jPanel1.add(associationListUI, gridBagConstraints);

		setLocation(30, 80);
		setSize(500, 500);
		setAlwaysOnTop(true);
		refresh();
	}

	protected abstract void removeRestrictions(Collection<Association> associations);

	/** This method is called from within the constructor to
	 * initialize the form.
	 * WARNING: Do NOT modify this code. The content of this method is
	 * always regenerated by the Form Editor.
	 */
	// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
	private void initComponents() {
		java.awt.GridBagConstraints gridBagConstraints;

		jPanel1 = new javax.swing.JPanel();
		jLabel1 = new javax.swing.JLabel();
		rootNameLabel = new javax.swing.JLabel();

		setTitle("Closure Border");
		getContentPane().setLayout(new java.awt.GridBagLayout());

		jPanel1.setLayout(new java.awt.GridBagLayout());

		jLabel1.setText("Closure-Border of ");
		gridBagConstraints = new java.awt.GridBagConstraints();
		gridBagConstraints.gridx = 1;
		gridBagConstraints.gridy = 1;
		jPanel1.add(jLabel1, gridBagConstraints);

		rootNameLabel.setText("jLabel2");
		gridBagConstraints = new java.awt.GridBagConstraints();
		gridBagConstraints.gridx = 2;
		gridBagConstraints.gridy = 1;
		gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
		gridBagConstraints.weightx = 1.0;
		jPanel1.add(rootNameLabel, gridBagConstraints);

		gridBagConstraints = new java.awt.GridBagConstraints();
		gridBagConstraints.gridx = 1;
		gridBagConstraints.gridy = 1;
		gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
		gridBagConstraints.weightx = 1.0;
		gridBagConstraints.weighty = 1.0;
		gridBagConstraints.insets = new java.awt.Insets(4, 2, 0, 2);
		getContentPane().add(jPanel1, gridBagConstraints);

		pack();
	}// </editor-fold>//GEN-END:initComponents

	// Variables declaration - do not modify//GEN-BEGIN:variables
	private javax.swing.JLabel jLabel1;
	private javax.swing.JPanel jPanel1;
	private javax.swing.JLabel rootNameLabel;
	// End of variables declaration//GEN-END:variables
	
	/**
	 * Refreshes view after model changes.
	 */
	public void refresh() {
		List<Table> roots = getRoots();
		DataModel datamodel = getDataModel();
		if (roots != null && !roots.isEmpty() && datamodel != null) {
			Set<Association> border = new HashSet<Association>();
			Set<Table> closure = new HashSet<>();
			for (Table root: roots) {
				if (root != null) {
					closure.addAll(root.closure(closure));
				}
			}
			rootNameLabel.setText(datamodel.getDisplayName(roots.get(0)) + (roots.size() <= 1? "": (" and additional subjects (" + (roots.size() - 1) + ")")));
			for (Table table: closure) {
				for (Association association: table.associations) {
					if (association.isIgnored() && !closure.contains(association.destination)) {
						border.add(association);
					}
				}
			}
			Collection<AssociationModel> model = new ArrayList<AssociationListUI.AssociationModel>();
			for (Association association: border) {
				model.add(new DefaultAssociationModel(association));
			}
			associationListUI.setModel(model);
		}
	}

	protected abstract List<Table> getRoots();
	protected abstract DataModel getDataModel();
	protected abstract void onSelect(Association association);

}
